#pragma once
#include "../common/message.hpp"
#include "../common/net.hpp"
#include "requestor.hpp"
#include <future>

namespace rpc
{
    namespace client
    {
        // 客户端通过该模块来对服务端发送rpc请求
        class RpcCaller
        {
        public:
            using ptr = std::shared_ptr<RpcCaller>;
            using JsonAsync = std::future<Json::Value>;
            using JsonCallback = std::function<void(const Json::Value &)>;
            RpcCaller(Requestor::ptr &requestor)
                : _Requestor(requestor)
            {
            }
            //
            // 实现回调函数
            // 同步调用
            bool call(const BaseConnection::ptr &conn, const std::string &method, Json::Value &params, Json::Value &result)
            {
                // 组织请求
                auto rpc_req = MessageFactory::create<RpcRequest>();
                rpc_req->setId(UUID::uuid());
                rpc_req->setMytype(MY_TYPE::REQ_RPC);
                rpc_req->setMethod(method);
                rpc_req->setParams(params);
                // 发送请求
                BaseMessage::ptr msg = MessageFactory::create(MY_TYPE::REQ_RPC);
                bool ret = _Requestor->send(conn, rpc_req, msg);
                if (ret == false)
                {
                    errlog("同步rpc响应失败");
                    return false;
                }
                // 等待响应
                auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(msg);
                if (!rpc_rsp_msg)
                {
                    errlog("rpc类型转换失败");
                    return false;
                }
                if (rpc_rsp_msg->getRecode() != MY_CODE::RCODE_OK)
                {
                    errlog("响应状态异常");
                    return false;
                }
                result = rpc_rsp_msg->getResult();
                return true;
            }
            // 异步调用
            bool call(const BaseConnection::ptr &conn, const std::string &mthod, Json::Value &params, JsonAsync &result)
            {
                // 组织请求：向服务器发送异步请求，在回调函数中传入一个promise对象，在回调函数中往promise设置结果
                auto rpc_req = MessageFactory::create<RpcRequest>();
                rpc_req->setId(UUID::uuid());
                rpc_req->setMytype(MY_TYPE::REQ_RPC);
                rpc_req->setMethod(mthod);
                rpc_req->setParams(params);

                // 构造异步调用智能指针
                auto json_promise = std::make_shared<std::promise<Json::Value>>();
                // 使用异步调用获取结果
                result = json_promise->get_future();

                Requestor::CallBack cb = std::bind(&RpcCaller::Callback, this, json_promise, std::placeholders::_1); // 设置promise关联
                bool ret = _Requestor->send(conn, std::dynamic_pointer_cast<BaseMessage>(rpc_req), cb);
                if (ret == false)
                {
                    errlog("异步请求失败");
                    return false;
                }

                delog("异步请求成功");
                return true;
            }
            // 回调调用
            bool call(const BaseConnection::ptr &conn, const std::string &mthod, Json::Value &params, const JsonCallback& result)
            {
                // 组织请求：向服务器发送异步请求，在回调函数中传入一个promise对象，在回调函数中往promise设置结果
                auto rpc_req = MessageFactory::create<RpcRequest>();
                rpc_req->setId(UUID::uuid());
                rpc_req->setMytype(MY_TYPE::REQ_RPC);
                rpc_req->setMethod(mthod);
                rpc_req->setParams(params);

                // 回调函数绑定
                Requestor::CallBack cb = std::bind(&RpcCaller::Callback1, this, result, std::placeholders::_1);
                bool ret = _Requestor->send(conn, std::dynamic_pointer_cast<BaseMessage>(rpc_req), cb);
                if (ret == false)
                {
                    errlog("回调请求失败");
                    return false;
                }
                return true;
            }

        private:
            void Callback(std::shared_ptr<std::promise<Json::Value>> &result, const BaseMessage::ptr &msg)
            {
                auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(msg);
                if (!rpc_rsp_msg)
                {
                    errlog("rpc类型转换失败");

                    if (rpc_rsp_msg->getRecode() != MY_CODE::RCODE_OK)
                    {
                        errlog("响应状态异常");
                    }
                }
                    // 将结果设置进入异步请求中
                    delog("设置异步响应结果");
                    result->set_value(rpc_rsp_msg->getResult());
                    delog("设置成功");
            }
            void Callback1(const JsonCallback &cb, const BaseMessage::ptr &msg)
            {
                auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(msg);
                if (!rpc_rsp_msg)
                {
                    errlog("rpc类型转换失败");
                }
                if (rpc_rsp_msg->getRecode() != MY_CODE::RCODE_OK)
                {
                    errlog("响应状态异常");
                }
                // 调用回调函数对结果进行处理
                cb(rpc_rsp_msg->getResult());
            }

        private:
            // 通过该成员来调用requestor里面的方法
            Requestor::ptr _Requestor;
        };
    }
}